Skip to content

feat(generator): build full SDK generation foundation - #7

Draft
nmorgan-cb wants to merge 14 commits into
mainfrom
toshi/plan-service-generator-upgrade
Draft

nmorgan-cb wants to merge 14 commits into
mainfrom
toshi/plan-service-generator-upgrade

Conversation

@nmorgan-cb

@nmorgan-cb nmorgan-cb commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Description

Adds a deterministic, OpenAPI-driven generator for the full Prime Java client surface (models, requests, responses, services, PrimeServiceFactory), and converges Java method/type names on the canonical names shared with the .NET, TypeScript, Python, and Go Prime SDKs — generating a @Deprecated compatibility alias for every existing public Java name that changes.

This PR adds the generator, its config, and tests. It does not include regenerated SDK source; see Generation preview below.

Generator

  • Committed spec (apiSpec/prime-public-spec.yaml) drives normal generation and CI; live fetch/diff is explicit and non-mutating.
  • Raw OpenAPI model/enum generation → post-processing → custom request/response/service/factory emission.
  • Preserves builders, pagination, status handling, /v1//v2 routing, PrimeXM* naming, and existing model transforms.
  • Routes *ErrorCode/*Subcode enums into com.coinbase.prime.model.errors.
  • make fetch-spec, make generate, make check-generated, make generate-live-diff — check/live-diff render only in isolated temp dirs, never mutate the checkout.

Canonical naming + generated deprecated aliases

Every alias is declared in operations-overrides.json, never hand-written:

{
  "operationId": "PrimeRESTAPI_CreateWalletTransfer",
  "sdkMethod": "CreateTransfer",
  "deprecatedAliases": [{ "sdkMethod": "CreateWalletTransfer", "message": "Use createTransfer instead." }]
}

For each entry, the generator emits a @Deprecated request subclass (with a covariant Builder subclass, so new LegacyRequest.Builder()...build() still compiles and returns the legacy type), a @Deprecated response subclass, and @Deprecated forwarding methods on the service interface and implementation.

Canonical Deprecated alias
createTransfer createWalletTransfer
createWithdrawal createWalletWithdrawal
getOrder getOrderByOrderId
claimStakingRewards claimRewards
createPortfolioStake portfolioStakingInitiate
createPortfolioUnstake portfolioStakingUnstake
listEntityPaymentMethods listPaymentMethods
getEntityPaymentMethod getPaymentMethodDetails
listActivities listPortfolioActivities
getAddressBook listAddressBook
getAllocationsByClientNettingId listAllocationsByNettingId

listEntityUsers, getEntityFcmBalance, and getPortfolioCounterpartyId stay canonical as-is.

config/naming-parity.json plus NamingParityTest lock this mapping in-repo, without cloning other SDK repositories in CI.

Tests

  • Generator: 39 tests (was 29) — adds DeprecatedAliasGenerationTest and NamingParityTest.
  • Root SDK: 285 tests, unaffected.

Generation preview

Ran make generate in an isolated git worktree, then compiled and tested the generated SDK (285 tests passing), including existing example programs, which compile with deprecation warnings on legacy calls. make check-generated reports new canonical types as additions and legacy names as converted alias files. The preview caught a real bug: alias Builder.build() initially skipped the canonical (private) validate(); it's now protected and called via super.validate().

The generated SDK baseline itself (models, DTOs, services, factory, error enums, manifest) will be committed in a follow-up, after a public API diff review, then make check-generated becomes a required CI gate.

Generated with Toshi

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Dependency update
  • Refactor / cleanup
  • Other (describe below)

Checklist

  • Tests included / updated
  • Changelog updated
  • Version bump if needed

@cb-heimdall

Copy link
Copy Markdown

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1

@nmorgan-cb
nmorgan-cb force-pushed the toshi/plan-service-generator-upgrade branch from d0671ee to 5e2693d Compare September 2, 2026 17:43
@nmorgan-cb nmorgan-cb changed the title feat(generator): add OpenAPI operation inventory feat(generator): build full SDK generation foundation Sep 2, 2026
nmorgan-cb and others added 10 commits September 2, 2026 16:43
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Co-authored-by: Toshi <toshi-noreply@coinbase.com>
Java converges on canonical cross-SDK method/type names while every
previously public Java name is preserved as a source-compatible,
generated deprecated alias, declared entirely from config:

- add `deprecatedAliases` to GeneratorConfiguration.Override, parsed
  from tools/model-generator/config/operations-overrides.json
- add DeprecatedAlias and OperationBinding.deprecatedAliases()
- OperationBindingValidator rejects an alias that matches its own
  canonical name or collides with another Java service method
- RequestPhase emits deprecated alias request classes as subclasses
  of the canonical request, with a covariant Builder subclass
  (including pagination builder methods and convenience
  constructors) so `new LegacyRequest.Builder()...build()` keeps
  compiling and returning the legacy type; the canonical builder's
  validate() is now protected so the alias build() can invoke it
- ResponsePhase emits deprecated alias response subclasses
- ServicePhase emits `@Deprecated` forwarding methods on both the
  service interface and implementation, with Javadoc pointing at the
  canonical method

Apply this to the 11 canonical/alias pairs agreed across the Java,
.NET, TypeScript, Python, and Go Prime SDKs: createTransfer,
createWithdrawal, getOrder, claimStakingRewards,
createPortfolioStake, createPortfolioUnstake,
listEntityPaymentMethods, getEntityPaymentMethod, listActivities,
getAddressBook, and getAllocationsByClientNettingId, keeping their
existing Java names generated as deprecated aliases. Removes the
hardcoded METHOD_RENAMES entries superseded by these declarative
overrides.

Add config/naming-parity.json plus NamingParityTest as a versioned,
in-repo fixture asserting the operation ID -> canonical Java
method/type -> legacy alias -> service folder mapping for both the
11 renamed operations and 3 operations whose existing Java name is
intentionally kept canonical (listEntityUsers, getEntityFcmBalance,
getPortfolioCounterpartyId). This does not clone or depend on the
other SDK repositories; it only locks the Java generator's own
naming decisions.

Add DeprecatedAliasGenerationTest covering config parsing, binding
validation, and the generated request/response/service alias shape
against a synthetic fixture.

Verified with an isolated `git worktree add --detach` generation
preview (not committed): `make generate` + `mvn test` produce a
compiling, fully passing (285 tests) SDK where every legacy Java
name still compiles, still returns the same public type, and now
carries a deprecation warning pointing at its canonical replacement.

Co-authored-by: Toshi <toshi-noreply@coinbase.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants